# -*- coding: utf-8 -*-
# @Time: 2024/10/24 23:53
# @Author: foxhuty
# @File: newgaokao.py

import pandas as pd
from sympy import symbols, solve


class DataSource:
    A_T_range = [86, 100]
    B_T_range = [71, 85]
    C_T_range = [56, 70]
    D_T_range = [41, 55]
    E_T_range = [30, 40]

    def __init__(self, file):
        self.file = file

    def get_data(self):
        try:
            excel_file = pd.ExcelFile(self.file)
            return [pd.read_excel(excel_file, sheet_name) for sheet_name in excel_file.sheet_names]
        except Exception as e:
            print(f"Error reading Excel file: {e}")
            return []

    def get_grade_data(self):
        data_list = self.get_data()
        if not data_list:
            return
        data = data_list[1]
        subjects = [col for col in data.columns if col in ['政治', '地理', '生物', '化学']]
        for subject in subjects:
            data = self.get_grade(data, subject)
            data.to_excel(self.file.split('.xlsx')[0] + '等级赋分表.xlsx', index=False)
            print('successfully done')

    def get_grade(self, data, subject):
        max_score, min_score = self.get_subject_max_min_score(data, subject)
        data[subject + '等级'] = data[subject].apply(lambda x:get_level(x, min_score))
        data[subject + '赋值'] = data[subject].apply(
            lambda x: self.get_final_scores(x, min_score, max_score))
        return data

    def get_subject_max_min_score(self, data, subject):
        # Simplified and optimized calculation
        subject_num = data[subject].count_distribution = [0.15, 0.35, 0.35, 0.13]
        cumulative_distribution = [sum(grade_distribution[:i + 1]) for i in range(len(grade_distribution))]
        data.sort_values(by=subject, ascending=False, inplace=True, ignore_index=True)

        thresholds = {}
        current_index = 0
        for i, percentage in enumerate(cumulative_distribution):
            current_index += int(subject_num * percentage)
            thresholds[i] = (data.iloc[current_index][subject],
                             [current_index - int(subject_num * percentage)][subject] if current_index > 0 else 0)
        return [max(scores) for scores in thresholds.values()], [min(scores) for scores in thresholds.values()]

    def get_final_scores(self, score, min_score, max_score):
        grade_ranges = [self.A_T_range, self.B_T_range, self.C_T_range, self.D_T_range, self.E_T_range]
        for i, (min_s, max_s) in enumerate(zip(min_score, max_score)):
            if score >= min_s:
                return round(self.get_added_score(score, min_s, max_s, grade_ranges[i][0], grade_ranges[i][1]))

    @staticmethod
    def get_added_score(y, y1, y2, t1, t2):
        t = symbols('t')
        if y == y1:
            return t1
        else:
            scores_added = solve((t2 - t) / (t - t1) - (y2 - y) / (y - y1), t)
            return round(scores_added[0])
